from .base import FactorBase

# from .factor2 import CFO, Pascal, RVI, TsFresh
from .factor_kline import FactorKline
from collections import defaultdict, deque


all_factor_objs: list[FactorBase]
# all_factor_objs = [RVI(14), Pascal(14), CFO(14), TsFresh(14)]
all_factor_objs = [FactorKline()]
# all_factor_objs = [RVI(14), Pascal(14), FactorKline()]
bfname_obj: dict[str, FactorBase] = {x.bfname: x for x in all_factor_objs}

bfname_names: dict[str, list[str]] = {x.bfname: x.fname_list for x in all_factor_objs}

name_bfname: dict[str, str] = {
    y: x for x, y_list in bfname_names.items() for y in y_list
}


def _get_direct_relays(bfnames: list[str]):
    mm = {}
    bfnames = list(set(bfnames))
    for bfname in bfnames:
        if (
            not hasattr(bfname_obj[bfname], "depend_fnames")
            or not bfname_obj[bfname].depend_fnames
        ):
            mm[bfname] = []
            continue
        depend_fnames = bfname_obj[bfname].depend_fnames
        depend_bfnames = list(set([name_bfname[x] for x in depend_fnames]))
        mm[bfname] = depend_bfnames
        mm.update(_get_direct_relays([x for x in depend_bfnames if x not in mm]))
    return mm


def bfnames_order(bfnames: list[str], need_relays: bool = False) -> list[str]:
    dependencies = _get_direct_relays(bfnames)
    graph = defaultdict(list)  # 任务 -> 依赖它的任务
    in_degree = {task: 0 for task in dependencies}  # 任务 -> 依赖数

    for task, deps in dependencies.items():
        for dep in deps:
            graph[dep].append(task)  # 依赖任务 -> 影响的任务
            in_degree[task] += 1  # 统计每个任务的入度

    # 2. 拓扑排序（按层次执行）
    result = []  # 存储分批执行的任务
    queue = deque(
        [task for task in dependencies if in_degree[task] == 0]
    )  # 初始无依赖任务

    while queue:
        current_group = list(queue)  # 当前批次任务
        result.append(current_group)  # 添加到结果中
        queue.clear()  # 清空队列，准备存放下批次任务

        for task in current_group:
            for dependent in graph[task]:  # 影响的任务
                in_degree[dependent] -= 1  # 依赖数减一
                if in_degree[dependent] == 0:  # 如果没有依赖，加入队列
                    queue.append(dependent)

    for task, num in in_degree.items():
        if num != 0:
            raise Exception(f"有任务的某些依赖没有完成，请检查错误，{task}")
    if not need_relays:
        for i in range(len(result)):
            result[i] = [x for x in result[i] if x in bfnames]
        result = [x for x in result if x]
    return result
